﻿using Microsoft.Extensions.Configuration;

using System.Security.Cryptography;
using System.Text;

namespace WXWorkSvc.Common.Extensions;
public class CryptographyConfig
{

}

public class Cryptography
{
    private const string SectionName = "Cryptography";
    private readonly string _Token;
    public readonly byte[] _Key, _IV;
    public Cryptography(IConfiguration configuration)
    {
        _Token = configuration[SectionName + ":Token"]!;
        _Key = Convert.FromBase64String(configuration[SectionName + ":EncodingAESKey"]! + "=");
        _IV = _Key.Take(16).ToArray();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="msgSignature"></param>
    /// <param name="timeStamp"></param>
    /// <param name="nonce"></param>
    /// <param name="encryptMsg"></param>
    /// <param name="decryptMsg"></param>
    /// <param name="receiveId">企业应用的回调，表示corpid
    /// 第三方事件的回调，表示suiteid
    /// 个人主体的第三方应用的回调，ReceiveId是一个空字符串</param>
    /// <returns></returns>
    public bool VerifyURL(string msgSignature, string timeStamp, string nonce, string encryptMsg, out string decryptMsg, out string receiveId)
    {


        var inputBytes = Encoding.UTF8.GetBytes(string.Join("", new List<string>
        {
          _Token,timeStamp,nonce,encryptMsg
        }.OrderBy(ii => ii)));

        var sign = inputBytes.Sha1Sign();
        if (msgSignature != sign)
        {
            decryptMsg = receiveId = "";
            return false;
        }
        var bytes = Convert.FromBase64String(encryptMsg).AesDecrypt(_Key, _IV);
        var lenBytes = new Span<byte>(bytes, 16, 4);
        lenBytes.Reverse();
        var len = BitConverter.ToInt32(lenBytes);
        decryptMsg = Encoding.UTF8.GetString(bytes.Skip(20).Take(len).ToArray());
        receiveId = Encoding.UTF8.GetString(bytes.Skip(20 + len).ToArray());
        return true;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="msgSignature"></param>
    /// <param name="timeStamp"></param>
    /// <param name="nonce"></param>
    /// <param name="encryptMsg">Body的jsonstring</param>
    /// <param name="decryptMsg"></param>
    /// <returns></returns>
    public bool VerifyURL<T>(string msgSignature, string timeStamp, string nonce, string encryptMsg, out T? decryptMsg)
    {


        var inputBytes = Encoding.UTF8.GetBytes(string.Join("", new List<string>
        {
          _Token,timeStamp,nonce,encryptMsg
        }.OrderBy(ii => ii)));

        var sign = inputBytes.Sha1Sign();
        if (msgSignature != sign)
        {
            decryptMsg = default;
            return false;
        }
        var bytes = Encoding.UTF8.GetBytes(encryptMsg).AesDecrypt(_Key, _IV);
        decryptMsg = bytes.To<T>();
        return true;
    }

    //public static string GetJSSign(string jsapi_ticket, string noncestr, string timestamp, string url)
    //{
    //    var str = $"jsapi_ticket={jsapi_ticket}&noncestr={noncestr}&timestamp={timestamp}&url={url}";
    //    using var sha = SHA1.Create();
    //    var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(str));
    //    var sb = new StringBuilder();
    //    foreach (var b in bytes)
    //        sb.Append(b.ToString("x2"));
    //    return sb.ToString();
    //}
}
